package com.xuxueli.applyModules.utils.testssh2;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;

@Slf4j
public class RemoteServerOptUtil {

    private static final String DEFAULT_CHARSET = "UTF-8";

    /**
     * 使用用户名密码，创建远程ssh连接
     * @param host
     * @param port
     * @param sshUser
     * @param sshPwd
     * @return
     * @throws Exception
     */
    public static Connection conToHostBySSH(String host, Integer port, String sshUser, String sshPwd) throws Exception{
        Connection conn=null;
        try {
            conn= new Connection(host, port);
            conn.connect();
            boolean isAuthenticated = conn.authenticateWithPassword(sshUser, sshPwd);

            if (isAuthenticated == false){
                System.out.println("密码错误");
                throw new IOException("Authentication failed.");
            }
        } catch (Exception e){
            conn=null;
            throw e;
        } finally {
            return conn;
        }
    }

    /**
     * 上传文件到远程文件夹
     * @param conn
     * @param localFilePath
     * @param remoteFolderPath
     * @throws IOException
     */
    public static void uploadFile(Connection conn,String localFilePath,String remoteFolderPath) throws IOException{
        SCPClient client=new SCPClient(conn);
        log.debug("将要上传文件：{}到远程目录:{}",localFilePath,remoteFolderPath);
        client.put(localFilePath, remoteFolderPath);
    }

    public static void main(String[] args) {
        String random = RandomStringUtils.random(4, false, true);
        System.out.println("随机数"+random);
        Properties props=System.getProperties(); //系统属性或者直接用System.getProperty("propertyName");
        System.out.println("Java的运行环境版本："+props.getProperty("java.version"));
        System.out.println("Java的运行环境供应商："+props.getProperty("java.vendor"));
        System.out.println("Java供应商的URL："+props.getProperty("java.vendor.url"));
        System.out.println("Java的安装路径："+props.getProperty("java.home"));
        System.out.println("Java的虚拟机规范版本："+props.getProperty("java.vm.specification.version"));
        System.out.println("Java的虚拟机规范供应商："+props.getProperty("java.vm.specification.vendor"));
        System.out.println("Java的虚拟机规范名称："+props.getProperty("java.vm.specification.name"));
        System.out.println("Java的虚拟机实现版本："+props.getProperty("java.vm.version"));
        System.out.println("Java的虚拟机实现供应商："+props.getProperty("java.vm.vendor"));
        System.out.println("Java的虚拟机实现名称："+props.getProperty("java.vm.name"));
        System.out.println("Java运行时环境规范版本："+props.getProperty("java.specification.version"));
        System.out.println("Java运行时环境规范供应商："+props.getProperty("java.specification.vender"));
        System.out.println("Java运行时环境规范名称："+props.getProperty("java.specification.name"));
        System.out.println("Java的类格式版本号："+props.getProperty("java.class.version"));
        System.out.println("Java的类路径："+props.getProperty("java.class.path"));
        System.out.println("加载库时搜索的路径列表："+props.getProperty("java.library.path"));
        System.out.println("默认的临时文件路径："+props.getProperty("java.io.tmpdir"));
        System.out.println("一个或多个扩展目录的路径："+props.getProperty("java.ext.dirs"));
        System.out.println("操作系统的名称："+props.getProperty("os.name"));
        System.out.println("操作系统的构架："+props.getProperty("os.arch"));
        System.out.println("操作系统的版本："+props.getProperty("os.version"));
        System.out.println("文件分隔符："+props.getProperty("file.separator"));//在 unix 系统中是"/"
        System.out.println("路径分隔符："+props.getProperty("path.separator"));//在 unix 系统中是":"
        System.out.println("行分隔符："+props.getProperty("line.separator"));//在 unix 系统中是"/n"
        System.out.println("用户的账户名称："+props.getProperty("user.name"));
        System.out.println("用户的主目录："+props.getProperty("user.home"));
        System.out.println("用户的当前工作目录："+props.getProperty("user.dir"));
        System.out.println("默认的临时文件路径："+ RemoteServerOptUtil.class.getResource("").getPath());
    }

    /**
     * 执行远程命令
     * @param cmd
     * @param con
     * @throws IOException
     */
    public static void execmd(String cmd,Connection con) throws IOException{
        Session session = null;
        session = con.openSession();
        try {
            session.execCommand(cmd);
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if(session!=null){
                session.close();
            }
        }
    }
    /**
     * @Description: 下载文件,只能下载文件类型, 如果是目录则抛出异常
     * @param connection ssh2 连接对象
     * @param remoteFilePathAbs 远程文件绝对路径名
     * @param localDir 本地文件夹
     * @author: zongf
     * @time: 2019-03-25 21:41:33
     */
    public static void download(Connection connection, String localDir, String... remoteFilePathAbs) {

        // 如果传参为空, 则返回
        if(remoteFilePathAbs == null){
            return;
        }

        SCPClient scpClient = new SCPClient(connection);

        try {
            scpClient.get(remoteFilePathAbs, localDir);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * @Description: 执行一条命令
     * @param connection ssh2 连接对象
     * @return: ExecCmdResult 执行结果, 封装执行状态和执行结果
     * @author: zongf
     * @time: 2019-03-25 20:47:14
     */
    public static ExecCmdResult execCommand(Connection connection, String command) {

        ExecCmdResult execCmdResult = new ExecCmdResult();

        Session session = null;

        try {
            session = connection.openSession();

            // 执行命令
            session.execCommand(command);

            // 解析结果
            String result = parseResult(session.getStdout());

            // 若解析结果为空, 则表示执行命令发生了错误, 尝试解析错误输出
            if (result.isEmpty()) {
                result = parseResult(session.getStderr());
            }else {
                execCmdResult.setSuccess(true);
            }

            // 设置响应结果
            execCmdResult.setResult(result);

            return execCmdResult;

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (session != null) {
                session.close();
            }
        }
        return null;
    }

    /**
     * @Description: 通配符方式下载文件
     * @param connection ssh2 连接对象
     * @param remoteDirAbsPath 远程文件绝对路径
     * @param fileNamePattern 文件名通配符匹配模式
     * @param localDir 本地目录, 可接受相对绝对路径
     * @author: zongf
     * @time: 2019-03-25 22:20:07
     */
    public static void downloadByPattern(Connection connection, String localDir, String remoteDirAbsPath, String fileNamePattern) {

        ExecCmdResult execCmdResult = execCommand(connection, "ls " + remoteDirAbsPath + "/" + fileNamePattern);
        if (execCmdResult.isSuccess()) {

            String[] files = execCmdResult.getResult().split("\n");

            SCPClient scpClient = new SCPClient(connection);

            try {
                scpClient.get(files, localDir);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * @Description: 上传文件至远程服务器. 本地文件不存在时, 抛出异常,但会上传一个0字节的文件; 远程目录不存在时, 抛出异常.
     * @param connection ssh2 连接对象
     * @param remoteDirAbsPath 远程服务器文件夹, 必须是绝对路径
     * @param localFile 本地文件列表, 可接受绝对路径相对路径参数
     * @author: zongf
     * @time:  2018-03-25 21:44:07
     */
    public static void upload(Connection connection, String remoteDirAbsPath, String... localFile) {

        // 如果传参为空, 则返回
        if(localFile == null){
            return;
        }
        SCPClient scpClient = new SCPClient(connection);
        try {
            scpClient.put(localFile, remoteDirAbsPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description: 解析命令结果
     * @param inputStream 输入流
     * @return: String 字符串
     * @author: zongf
     * @time:  2019-03-25 21:06:23
     */
    private static String parseResult(InputStream inputStream) throws IOException {
        // 读取输出流内容
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, DEFAULT_CHARSET));
        StringBuffer resultSb = new StringBuffer();
        String line;
        while ((line = br.readLine()) != null) {
            resultSb.append(line + "\n");
        }
        return resultSb.toString();
    }
}